package com.example.shiro.shiro.controller;

import com.example.shiro.shiro.enums.OperationType;
import com.example.shiro.shiro.log.SystemLog;
import com.example.shiro.shiro.model.SysUser;
import com.example.shiro.shiro.model.UserLine;
import com.example.shiro.shiro.service.SysUserService;
import com.example.shiro.shiro.utils.SystemConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author chong
 * @create 2020/3/27
 * Desc: 系统用户
 */
@Slf4j
@RestController
public class SysUserController extends BaseController {
    @Autowired
    private SessionDAO sessionDAO;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 登录
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/login")
    public Map<String, Object> login(@RequestBody SysUser sysUser) {
        Map<String, Object> data = new HashMap<>();
        data.put("success", true);
        try {
            Subject subject = SecurityUtils.getSubject();
            Collection<Session> sessions = sessionDAO.getActiveSessions();
            UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getLoginName(), sysUser.getPassword());
            for (Session s : sessions) {
                if (null == s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)) {
                    continue;
                }
                if (sysUser.getLoginName().equals(s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY).toString())) {
//                    sessionDAO.delete(s); // session清除
                    s.setAttribute(SystemConsts.OFF_LINE, true);
//                    s.setTimeout(0); // 这里就把session清除
                }
            }
            try {
                subject.login(token);
            } catch (UnknownAccountException uae) {
                data.put("success", false);
                data.put("msg", "未知账户");
            } catch (IncorrectCredentialsException ice) {
                data.put("success", false);
                data.put("msg", "密码不正确");
            } catch (LockedAccountException lae) {
                data.put("success", false);
                data.put("msg", "账户已锁定");
            } catch (ExcessiveAttemptsException eae) {
                data.put("success", false);
                data.put("msg", "用户名或密码错误次数过多");
            } catch (AuthenticationException ae) {
                data.put("success", false);
                data.put("msg", "用户名或密码不正确");
            }
            subject.getSession().setAttribute("loginName", sysUser.getLoginName());
            subject.getSession(true).setAttribute("userName", sysUser.getLoginName());
            data.put("sessionId", subject.getSession().getId());
            if (subject.isAuthenticated()) {
//                    SystemConsts.session_map.put((String) subject.getSession().getId(),"true");
                subject.getSession().setAttribute(SystemConsts.OFF_LINE, false);
            } else {
                data.put("success", false);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            data.put("success", false);
            return data;
        }
        return data;
    }

    /**
     * 注册
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/register")
    public Map<String, Object> register(@RequestBody SysUser sysUser) {
        Map<String, Object> data = new HashMap<>();
        data.put("success", true);
        try {
            Object pwdObj = new SimpleHash("md5", sysUser.getPassword(), null, 2);
            sysUser.setPassword(pwdObj.toString());
            sysUserService.add(sysUser);
        } catch (Exception e) {
            log.error(e.getMessage());
            data.put("success", false);
        }
        return data;
    }

    /**
     * 注销
     *
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public Map<String, Object> logout(HttpServletRequest request) {
        Map<String, Object> data = new HashMap<>();
        data.put("success", true);
        try {
            Subject currentUser = SecurityUtils.getSubject();
            currentUser.logout();
        } catch (Exception e) {
            log.error(e.getMessage());
            data.put("success", false);
        }
        return data;
    }

    /**
     * 获取在线用户
     *
     * @return
     */
    @GetMapping(value = "/getUserLineList")
    public Map<String, Object> getUserLineList() {
        Map<String, Object> data = new HashMap<>();
        data.put("success", true);
        try {
            List<UserLine> lineList = new ArrayList<>();
            Collection<Session> sessions = sessionDAO.getActiveSessions();
            for (Session s : sessions) {
                UserLine userLine = new UserLine();
                if (null == s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)) {
                    continue;
                } else {
                    userLine.setAccount(s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY).toString());
                }
                userLine.setHost(s.getHost());
                userLine.setId((String) s.getId());
                userLine.setStartTime(s.getStartTimestamp());
                userLine.setLastAccessTime(s.getLastAccessTime());
                userLine.setSetTimeout(s.getTimeout());
                lineList.add(userLine);
            }
            data.put("data", lineList);
        } catch (BeansException e) {
            log.error("[获取在线人数]异常", e.getMessage());
            data.put("success", false);
        }
        return data;
    }

    /**
     * 校验sessionId
     *
     * @param request
     * @return
     */
    @SystemLog(modelName ="用户管理",operationType = OperationType.SELECT,operationName = "校验sessionId")
    @GetMapping(value = "/checkAuthStatus")
    public Map<String, Object> checkAuthStatus(HttpServletRequest request) {
        Map<String, Object> data = new HashMap<>();
        data.put("success", true);
        try {
            String id = WebUtils.toHttp(request).getHeader("Authorization");
            Session session = sessionDAO.readSession(id);
            if (session.getAttribute(SystemConsts.OFF_LINE).toString().equals("true")) {
                data.put("data", 1);
                data.put("msg", "被迫下线");
            } else {
                data.put("data", 0);
                data.put("msg", "正常登录");
            }
        } catch (BeansException e) {
            log.error("[获取在线人数]异常", e.getMessage());
            data.put("success", false);
            data.put("msg", "不在线,session失效");
        }
        return data;
    }
}
